package openase.audiosearch.comm.response.encoder.factory;

import java.util.HashMap;
import java.util.Map;

import openase.audiosearch.comm.response.ExecutionError;
import openase.audiosearch.comm.response.RegistrationSuccessful;
import openase.audiosearch.comm.response.Response;
import openase.audiosearch.comm.response.SearchResult;
import openase.audiosearch.comm.response.UnknownRequest;
import openase.audiosearch.comm.response.encoder.ExecutionErrorResponseEncoder;
import openase.audiosearch.comm.response.encoder.RegistrationSuccessfulResponseEncoder;
import openase.audiosearch.comm.response.encoder.ResponseEncoder;
import openase.audiosearch.comm.response.encoder.SearchResultResponseEncoder;
import openase.audiosearch.comm.response.encoder.UnknownRequestResponseEncoder;


public class ResponseEncoderFactory {

	private static final Map<Class<? extends Response>, ResponseEncoder<? extends Response>> ENCODERS;
	static {
		ENCODERS = new HashMap<Class<? extends Response>, ResponseEncoder<? extends Response>>();
		ENCODERS.put(UnknownRequest.class, new UnknownRequestResponseEncoder());
		ENCODERS.put(ExecutionError.class, new ExecutionErrorResponseEncoder());
		ENCODERS.put(RegistrationSuccessful.class, new RegistrationSuccessfulResponseEncoder());
		ENCODERS.put(SearchResult.class, new SearchResultResponseEncoder());
	}

	private ResponseEncoderFactory() {
	}

	@SuppressWarnings("unchecked")
	public static <T extends Response> ResponseEncoder<T> getEncoder(T response) {
		if (response == null) {
			return null;
		}
		return (ResponseEncoder<T>) get(response.getClass());
	}

	private static ResponseEncoder<? extends Response> get(Class<?> clazz) {
		ResponseEncoder<? extends Response> encoder = ENCODERS.get(clazz);
		if (encoder != null) {
			return encoder;
		}
		encoder = get(clazz.getSuperclass());
		if (encoder != null) {
			return encoder;
		}
		for (Class<?> itfce : clazz.getInterfaces()) {
			encoder = get(itfce);
			if (encoder != null) {
				return encoder;
			}
		}
		return null;
	}

}